package com.github.willisaway.core.base;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.willisaway.core.mp.WhereEntityTool;
import com.github.willisaway.core.util.DataUtil;

/**
 * 业务逻辑层基类<br/>
 * 如果需要Redis缓存,继承基类后配置CacheConfig(cacheNames="")
 * 
 */
@CacheConfig(cacheNames = {"BaseService"})
public abstract class BaseService<M extends BaseMapper<T>,T extends BaseModel> extends ServiceImpl<M,T>{
    @Autowired
    protected M baseMapper;
    /** 获取分页对象 */
    public Page<T> getPage(BaseQuery query) {
        Integer current = 1;
        Integer size = 10;
        if (!StringUtils.isEmpty(query.getPageNum())) {
            current = query.getPageNum();
        }
        if (!StringUtils.isEmpty(query.getPageSize())) {
            size = Integer.valueOf(query.getPageSize());
        }
        Page<T> page = new Page<T>(current, size);
        page.setOrders(query.getSearchOrderItems());

        return page;
    }
    
    /** 获取分页对象 */
    public Page<T> getPage(Map<String, Object> params) {
        Integer current = 1;
        Integer size = 10;
        String orderBy = "";
        boolean isAsc=true;
        if (DataUtil.isNotEmpty(params.get("pageNum"))) {
            current = Integer.valueOf(params.get("pageNum").toString());
        }
        if (DataUtil.isNotEmpty(params.get("pageSize"))) {
            size = Integer.valueOf(params.get("pageSize").toString());
        }
        if (DataUtil.isNotEmpty(params.get("orderBy"))) {
            orderBy = (String) params.get("orderBy");
        }
        List<OrderItem> orderItems = new ArrayList<OrderItem>();
        if (!StringUtils.isEmpty(params.get("column"))) {
            String column = "";
            boolean asc = true;
            column = (String) params.get("column");
            OrderItem orderItem = new OrderItem();
            orderItem.setColumn(column);
            if (!StringUtils.isEmpty(params.get("asc"))) {
                asc = Boolean.valueOf(params.get("asc").toString());
                orderItem.setAsc(asc);
            }
            orderItems.add(orderItem);
        }
        Page<T> page = new Page<T>(current, size);
        page.setOrders(orderItems);
        return page;
    }

    @Transactional
    @CacheEvict()
    public void delete(Map params) {
        List<T> list = queryList(params);
        for(T record:list) {
            delete(record);
        }
    }
    
    @Transactional
    @CacheEvict(key="target.getCacheName() + ':' + #id")
    public Integer delete(Long id) {
        Long userId = -1L;//ContextHolder.getUserId();
        T record = this.queryById(id);
        record.setDeletedFlag("1");
        record.setUpdateBy(userId);
        return baseMapper.updateById(record);
    }
    
    @Transactional
    @CacheEvict(key="target.getCacheName() + ':' + #p0.rowId")
    public void delete(T record) {
        Long userId = -1L;//ContextHolder.getUserId();
        record.setDeletedFlag("1");
        record.setUpdateBy(userId);
        baseMapper.updateById(record);
    }
    
    @Transactional
    @CachePut(key="target.getCacheName() + ':' + #p0.rowId")
    public T update(T record) {
        Long userid = -1L;//ContextHolder.getUserId();
        if (record.getRowId() == null) {
            record.setCreateBy(userid);
            baseMapper.insert(record);
            record = queryById(record.getRowId());//数据库非主键字段的默认值,没有更新到bean中 2017年3月21日11:09:20 liyg
        } else {
            record.setUpdateBy(userid);
            baseMapper.updateById(record);
        }
        return record;
    }
    
    @Transactional
    @Cacheable(key="target.getCacheName() + ':' + #id")
    public T queryById(Long id) {
        T record = null;
        if (record == null) {
            record = baseMapper.selectById(id);
        }
        return record;
    }

    /**
     * 查询一个
     */
    public T queryOne(BaseQuery query) {
        Wrapper<T> wrapper = getWrapper(query);
        return getBaseMapper().selectOne(wrapper);
    }
    
    /**
     * 查询所有
     */
    public List<T> queryList(BaseQuery query) {
        Wrapper<T> wrapper = getWrapper(query);
        return getBaseMapper().selectList(wrapper);
    }

    /**
     * 查询，带分页
     */
    public Page<T> queryPage(BaseQuery query) {
        Page<T> page = getPage(query);
        QueryWrapper<T> wrapper = getWrapper(query);
        return getBaseMapper().selectPage(page, wrapper);
    }

    public QueryWrapper<T> getWrapper(BaseQuery query) {
        QueryWrapper<T> wrapper = new QueryWrapper<T>();
        WhereEntityTool whereEntityTool = new WhereEntityTool();
        wrapper = whereEntityTool.invoke(query);
        wrapper = wrapper(query, wrapper);
        List<OrderItem> orderItems = query.getSearchOrderItems();
        if (!CollectionUtils.isEmpty(orderItems)) {
            for (OrderItem orderItem : orderItems) {
                wrapper.orderBy(true, orderItem.isAsc(), orderItem.getColumn());
            }
        }
        return wrapper;
    }

    // 各个模块自己实现，替代mybatis配置文件中的where
    public QueryWrapper<T> wrapper(BaseQuery query, QueryWrapper<T> wrapper) {
        return wrapper;
    }
    
    /**
     * 查询一个
     */
    public T queryOne(Map<String, Object> params) {
    	Wrapper<T> wrapper = getWrapper(params);
        return getBaseMapper().selectOne(wrapper);
    }
    
    /**
     * 查询所有
     */
    public List<T> queryList(Map<String, Object> params) {
        Wrapper<T> wrapper = getWrapper(params);
        return getBaseMapper().selectList(wrapper);
    }

    /**
     * 查询，带分页
     */
    public Page<T> queryPage(Map<String, Object> params) {
        Page<T> page = getPage(params);
        QueryWrapper<T> wrapper = getWrapper(params);
        return getBaseMapper().selectPage(page, wrapper);
    }

    public QueryWrapper<T> getWrapper(Map<String, Object> params) {
        QueryWrapper<T> wrapper = new QueryWrapper<T>();
        wrapper.eq("DELETED_FLAG", "0");
        wrapper = wrapper(params, wrapper);
        return wrapper;
    }

    // 各个模块自己实现，替代mybatis配置文件中的where
    public QueryWrapper<T> wrapper(Map<String, Object> params, QueryWrapper<T> wrapper) {
        return wrapper;
    }
    /** 获取缓存键值 */
    public String getCacheName() {
        String cacheName = null;
        CacheConfig cacheConfig = getClass().getAnnotation(CacheConfig.class);
        if (cacheConfig == null || cacheConfig.cacheNames() == null
                || cacheConfig.cacheNames().length < 1) {
            cacheName = getClass().getName();
        } else {
            cacheName = cacheConfig.cacheNames()[0];
        }
        return cacheName;
    }
}
